<?php
/**
 * Created by PhpStorm.
 * User: s7175
 * Date: 2019/8/18
 * Time: 12:18
 */

namespace App\Console\Commands\System;

use foo\bar;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use SebastianBergmann\CodeCoverage\Report\PHP;

class CreateModel extends Command
{
    /**
     * 控制台命令 signature 的名称。
     *
     * @var string
     */
    protected $signature = 'make:model {tableName}';

    /**
     * 控制台命令说明。
     *
     * @var string
     */
    protected $description = '生成model';


    public function __construct()
    {
        parent::__construct();
    }

    public $model = [
        //注释
        'property' => '',
        //类名
        'className' => '',
        //表名字
        'tableName' => '',
        //运行填充的字段
        'fillable' => '',
        //验证规则
        'uniques' => '',
        'rules' => '',
        //字段名称
        'attribute' => '',
        //默认值
        'attributes' => '',
    ];

    public $table = "";
    public $filePath = "";
    public $tempPath = "./model.model";//模板地址

    /**
     * 执行控制台命令。
     *
     * @return mixed
     */
    public function handle()
    {
        //文件默认地址
        $this->filePath = base_path('app' . DIRECTORY_SEPARATOR . 'Http' . DIRECTORY_SEPARATOR . 'Models');
        $this->tempPath = base_path('app\console\commands\system\model.model');

        //
        $table = $this->argument('tableName');

        if (!Schema::hasTable($table)) {
            $this->info($table . '表不存在！');
        }
        $this->table = $table;

        $fileds = [];
        $info = DB::select("show full columns from `$table`");
        foreach ($info as $k => $item) {
            $fileds[$k]['field'] = $item->Field;
            $fileds[$k]['type'] = $item->Type;
            $fileds[$k]['length'] = $this->parseLength($item->Type);
            $fileds[$k]['null'] = $item->Null;
            $fileds[$k]['key'] = $item->Key;
            $fileds[$k]['default'] = $item->Default;
            $fileds[$k]['comment'] = $item->Comment;
        }

        $this->generate($fileds, $table);
        $this->create($fileds, $table);
    }

    /**
     * 长度解析
     */
    private function parseLength($type)
    {
        $length = 0;
        $grep = "/\((\d{0,10})\)/";
        $arr = [];
        preg_match_all($grep, $type, $arr);
        $length = isset($arr[1][0]) && !empty($arr[1][0]) ? $arr[1][0] : 0;
        return $length;
    }

    /**
     * 判断类型
     */
    private function isType($type)
    {
        $types = ['array', 'integer', 'string', 'double', 'float'];
        $databaseType = [
            'int' => 'integer',
            'tinyint' => 'integer',
            'double' => 'double',
            'datetime' => 'string',
            'char' => 'string',
            'varchar' => 'string',
            'decimal' => 'double',
            'float' => 'float'
        ];

        $dataType = substr($type, 0, strpos($type, '('));

        $newType = 'string';
        foreach ($databaseType as $key => $item) {
            if ($dataType == $key) {
                $newType = $item;
                break;
            }
        }
        return $newType;
    }

    private function paresRules($filed)
    {

        $rule = "";
        if (isset($filed['null']) && $filed['null'] == "NO") {
            $rule .= "required";
        }
        if ($filed['length'] > 0) {
            $rule .= "|max:" . $filed['length'];
        }
        if ($filed['key'] == "UNI") {
            $str = '$id=isset($data["id"])?$data["id"]:null;';
            $this->model['uniques']=PHP_EOL.$str.PHP_EOL;
            $rule .= "|unique:{$this->table},{$filed['field']},'." . '$id';
        } else {
            $rule .= "'";
        }

        $rule=ltrim($rule,"|");
        $rule="'".$rule;
        return $rule;
    }

    /**
     * 生成对应的类
     */
    public function generate($fileds, $table)
    {
        $this->model['className'] = ucfirst($table);
        $this->model['tableName'] = $table;

        $fillable = '';
        $rules = '';
        $attribute = '';
        $attributes = '';
        foreach ($fileds as $filed) {
            $fieldName = $filed['field'];
            $type = $this->isType($filed['type']);

            //生成注释
            $this->model['property'] .= PHP_EOL . "@property  $type $fieldName" . PHP_EOL;
            //排除id 和 时间
            $notArr = ['created_at', 'updated_at', 'id'];
            if (!in_array($filed['field'], $notArr)) {

                //运行填充的字段
                $fillable .= "'{$filed['field']}',";


                //验证规则
                $rules .= PHP_EOL . "'{$filed['field']}'=>{$this->paresRules($filed)}," . PHP_EOL;
            }

            //字段名称
            $attribute .= PHP_EOL . "'{$filed['field']}'=>'{$filed['comment']}'," . PHP_EOL;

            //默认值
            if (!empty($filed['default'])) {
                $attributes .= PHP_EOL . "'{$filed['field']}'=>'{$filed['default']}'," . PHP_EOL;
            }
        }

        //运行填充的字段
        $this->model['fillable'] = rtrim($fillable, ',');
        //字段名称
        $this->model['rules'] = $rules;
        $this->model['attribute'] = $attribute;
        $this->model['attributes'] = $attributes;
    }

    /**
     * 创建Model
     */

    public function create()
    {
        //读取模板
        $tempString = file_get_contents($this->tempPath);
        $tempString = str_replace('{{$className}}', $this->model['className'], $tempString);
        $tempString = str_replace('{{$property}}', $this->model['property'], $tempString);
        $tempString = str_replace('{{$tableName}}', $this->model['tableName'], $tempString);
        $tempString = str_replace('{{$fillable}}', $this->model['fillable'], $tempString);
        $tempString = str_replace('{{$rules}}', $this->model['rules'], $tempString);
        $tempString = str_replace('{{$uniques}}', $this->model['uniques'], $tempString);
        $tempString = str_replace('{{$attribute}}', $this->model['attribute'], $tempString);
        $tempString = str_replace('{{$attributes}}', $this->model['attributes'], $tempString);

        file_put_contents($this->filePath . DIRECTORY_SEPARATOR . $this->model['className'] . '.php', $tempString);

    }

}